package com.zc.wxPay.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.thoughtworks.xstream.XStream;
import com.zc.custom.domain.ChargeCustomOrderInfo;
import com.zc.custom.domain.ChargeCustomOrderInfoProcess;
import com.zc.custom.mapper.ChargeCustomOrderInfoMapper;
import com.zc.custom.mapper.ChargeCustomOrderInfoProcessMapper;
import com.zc.custom.mapper.ChargeCustomOrderInvoiceMapper;
import com.zc.custom.mapper.ChargeCustomUserMapper;
import com.zc.iotDevice.domain.ChargeStationPile;
import com.zc.iotDevice.domain.IotDeviceSubsidiary;
import com.zc.iotDevice.mapper.ChargeStationPileMapper;
import com.zc.iotDevice.mapper.IotDeviceSubsidiaryMapper;
import com.zc.operator.domain.ChargeStation;
import com.zc.operator.domain.ChargeStationPriceTactics;
import com.zc.operator.mapper.ChargeStationMapper;
import com.zc.operator.service.ChargeStationPriceTacticsService;
import com.zc.wxPay.domain.WxPay;
import com.zc.wxPay.entity.*;
import com.zc.wxPay.util.Configure;
import com.zc.wxPay.util.HttpRequest;
import com.zc.wxPay.util.RandomStringGenerator;
import com.zc.wxPay.util.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.crypto.Data;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Author:gaojikun
 * @Description: 微信支付相关接口
 */
@Service
public class WXPayService {

    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);

    @Autowired
    private ChargeCustomOrderInfoMapper chargeCustomOrderInfoMapper;

    @Autowired
    private IotDeviceSubsidiaryMapper iotDeviceSubsidiaryMapper;

    @Autowired
    private ChargeStationMapper chargeStationMapper;

    @Autowired
    private ChargeStationPileMapper chargeStationPileMapper;

    @Autowired
    private ChargeCustomUserMapper chargeCustomUserMapper;

    @Autowired
    private ChargeStationPriceTacticsService chargeStationPriceTacticsService;//策略

    @Autowired
    private ChargeCustomOrderInfoProcessMapper chargeCustomOrderInfoProcessMapper;//操作步骤


    /**
     * 关闭订单
     */
    @Transactional
    public WxPay closeOrder(WxPay wxpay) {
        try {
            //根据商户订单号查询
            ChargeCustomOrderInfo orderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(wxpay.getOutTradeNo());
            //查询场站信息
            ChargeStation chargeStation = chargeStationMapper.selectChargeStationByChargeStationCode(orderInfo.getChargeStationCode());

            OrderQueryInfo order = new OrderQueryInfo();
            order.setAppid(Configure.getAppID());
            order.setMch_id(chargeStation.getMchId());
            order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
            order.setOut_trade_no(wxpay.getOutTradeNo());
            //order.setSign_type("MD5");
            //生成签名
            String sign = Signature.getSign(order, chargeStation.getMchKey());
            order.setSign(sign);

            String result = HttpRequest.sendPost(Configure.getClose_url(), order);
//            System.out.println(result);

            XStream xStream = new XStream();
            xStream.alias("xml", CloseReturnInfo.class);
            xStream.ignoreUnknownElements();
            Class<?>[] classes = new Class[]{CloseReturnInfo.class};
            xStream.allowTypes(classes);
            Object preOrderResult = xStream.fromXML(result);
            ObjectMapper objectMapper = new ObjectMapper();
            CloseReturnInfo returnInfo = objectMapper.convertValue(preOrderResult, CloseReturnInfo.class);

            if ("SUCCESS".equals(returnInfo.getReturn_code())) {
                //逻辑处理
//                //根据商户订单号查询
//                ChargeCustomOrderInfo orderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(wxpay.getOutTradeNo());
                //修改订单状态为已关闭
                orderInfo.setOrderInfoStatus("3");
                orderInfo.setOrderStatus("3");
                orderInfo.setTotalMoney(new BigDecimal("0"));
                orderInfo.setPaymentAmount(new BigDecimal("0"));
                orderInfo.setTotalTime(0L);
                int i = chargeCustomOrderInfoMapper.updateChargeCustomOrderInfo(orderInfo);
                if (i == 1) {
                    wxpay.setStatus(200);
                    wxpay.setMsg("关闭订单成功!");
                    return wxpay;
                }
            }

            wxpay.setStatus(500);
            wxpay.setMsg("关闭订单失败!");
            return wxpay;
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("微信订单关闭：发生异常==============》" + e);
            wxpay.setStatus(500);
            wxpay.setMsg("关闭订单失败!");
            return wxpay;
        }
    }

    /**
     * 取消支付
     */
    @Transactional
    public WxPay disDeal(WxPay wxpay) {
        //根据商户订单号查询
        ChargeCustomOrderInfo orderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(wxpay.getOutTradeNo());
        orderInfo.setOrderInfoStatus("2");
        orderInfo.setOrderStatus("3");
        orderInfo.setTotalMoney(new BigDecimal("0"));
        orderInfo.setPaymentAmount(new BigDecimal("0"));
        orderInfo.setTotalTime(0L);
        int i = chargeCustomOrderInfoMapper.updateChargeCustomOrderInfo(orderInfo);
        if (i == 1) {
            wxpay.setStatus(200);
            wxpay.setMsg("取消支付成功!");
            return wxpay;
        } else {
            wxpay.setStatus(500);
            wxpay.setMsg("取消支付失败!");
            return wxpay;
        }
    }

    /**
     * 下单
     */
    @Transactional
    public WxPay payment(WxPay wxpay) {
        String money = wxpay.getMoney();
        String title = wxpay.getTitle();
        String openid = wxpay.getOpenid();
        String ip = wxpay.getIp();

        if (StringUtils.isEmpty(money) || StringUtils.isEmpty(title) || StringUtils.isEmpty(openid) || StringUtils.isEmpty(ip)) {
            return null;
        }

        try {
            //查询场站信息
            ChargeStation chargeStation = chargeStationMapper.selectChargeStationByChargeStationCode(wxpay.getChargeStationCode());

            OrderInfo order = new OrderInfo();
            order.setAppid(Configure.getAppID());
            order.setMch_id(chargeStation.getMchId());
            order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
            order.setBody(title);
            order.setOut_trade_no(RandomStringGenerator.getRandomStringByLength(32));
            order.setTotal_fee(new BigDecimal(money).multiply(new BigDecimal("100")).intValue());
            order.setSpbill_create_ip(ip);
            order.setNotify_url(Configure.getNotify_url());
            order.setTrade_type(Configure.getTrade_type());
            order.setOpenid(openid);
            order.setSign_type("MD5");
            //生成签名
            String sign = Signature.getSign(order, chargeStation.getMchKey());
            order.setSign(sign);

            String result = HttpRequest.sendPost(Configure.getUrl(), order);
            //返回信息
//            System.out.println("微信统一下单：result=========》" + result);
            XStream xStream = new XStream();
            xStream.alias("xml", OrderReturnInfo.class);
            xStream.ignoreUnknownElements();
            Class<?>[] classes = new Class[]{OrderReturnInfo.class};
            xStream.allowTypes(classes);
            Object preOrderResult = xStream.fromXML(result);
            ObjectMapper objectMapper = new ObjectMapper();
            OrderReturnInfo returnInfo = objectMapper.convertValue(preOrderResult, OrderReturnInfo.class);

            // 二次签名
            if ("SUCCESS".equals(returnInfo.getReturn_code()) && returnInfo.getReturn_code().equals(returnInfo.getResult_code())) {
                SignInfo signInfo = new SignInfo();
                signInfo.setAppId(Configure.getAppID());
                long time = System.currentTimeMillis() / 1000;
                signInfo.setTimeStamp(String.valueOf(time));
                signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(32));
                signInfo.setRepay_id("prepay_id=" + returnInfo.getPrepay_id());
                signInfo.setSignType("MD5");
                //生成签名
                String sign1 = Signature.getSign(signInfo, chargeStation.getMchKey());
//                System.out.println("微信统一下单：sign========>" + sign1);
                Map<String, String> payInfo = new HashMap<>();
                payInfo.put("paySign", sign1);
                payInfo.put("timeStamp", signInfo.getTimeStamp());
                payInfo.put("nonceStr", signInfo.getNonceStr());
                payInfo.put("package", signInfo.getRepay_id());
                payInfo.put("signType", signInfo.getSignType());
                payInfo.put("orderCode", order.getOut_trade_no());

                wxpay.setOutTradeNo(order.getOut_trade_no());
                wxpay.setStatus(200);
                wxpay.setMsg("统一下单成功!");
                wxpay.setData(payInfo);

                // 添加订单信息至数据库
                ChargeCustomOrderInfo orderInfo = new ChargeCustomOrderInfo();
                orderInfo.setOrderInfoCode(order.getOut_trade_no());//商户订单号
                orderInfo.setCustomCode(openid);//客户编号
                orderInfo.setPreOrderCode(returnInfo.getPrepay_id());//预下单订单
                orderInfo.setDeviceCode(String.valueOf(wxpay.getDeviceId()));//设备ID
                orderInfo.setDeviceName(String.valueOf(wxpay.getDeviceName()));//设备名称
                orderInfo.setPortId(String.valueOf(wxpay.getPortId()));//设备端口ID
                orderInfo.setPortName(wxpay.getPortName());//设备端口
                orderInfo.setCreateTime(DateUtils.getNowDate());//创建时间
                orderInfo.setOperatorCode(chargeStation.getOperatorCode());//运营商Code
                orderInfo.setChargeStationCode(chargeStation.getChargeStationCode());//场站Code
                orderInfo.setOperatorName(chargeStation.getOperatorName());//运营商
                orderInfo.setChargeStationName(chargeStation.getChargeStationName());//场站
                orderInfo.setPaymentMethod("4");//支付方式 微信支付
                orderInfo.setTotalMoney(new BigDecimal(money));//订单金额
                orderInfo.setMchId(chargeStation.getMchId());//商户号
                //添加计费模版
                ChargeStationPriceTactics chargeStationPriceTactics = new ChargeStationPriceTactics();
                chargeStationPriceTactics.setStationCode(chargeStation.getChargeStationCode());
                chargeStationPriceTactics.setIsDefault("0");
                ChargeStationPriceTactics stationNowTactics = chargeStationPriceTacticsService.getStationNowTactics(chargeStationPriceTactics);
                if (stationNowTactics != null) {
                    orderInfo.setPriceTypeCode(stationNowTactics.getPriceTypeCode());//计费模版code
                    orderInfo.setPriceTypeName(stationNowTactics.getTacticsName());//策略name
                }
                //操作步骤 - 创建订单
                ChargeCustomOrderInfoProcess chargeCustomOrderInfoProcess = new ChargeCustomOrderInfoProcess();
                chargeCustomOrderInfoProcess.setOrderInfoCode(order.getOut_trade_no());//订单号
                chargeCustomOrderInfoProcess.setOrderInfoProcessName("创建订单");
                chargeCustomOrderInfoProcess.setCustomCode(openid);//openid
                chargeCustomOrderInfoProcess.setOrderInfoProcessResult("1");
                chargeCustomOrderInfoProcess.setOrderInfoProcessCreateTime(new Date());//时间
                List<ChargeCustomOrderInfoProcess> addlist = new ArrayList<ChargeCustomOrderInfoProcess>() {{
                    add(new ChargeCustomOrderInfoProcess(order.getOut_trade_no(), openid, "创建订单", "1", new Date()));
                    add(new ChargeCustomOrderInfoProcess(order.getOut_trade_no(), openid, "开始充电", "0", null));
                    add(new ChargeCustomOrderInfoProcess(order.getOut_trade_no(), openid, "结束充电", "0", null));
                    add(new ChargeCustomOrderInfoProcess(order.getOut_trade_no(), openid, "结算完毕", "0", null));
                }};
                boolean isAddList = chargeCustomOrderInfoProcessMapper.batchInsertChargeCustomOrderInfoProcess(addlist);
                if (!isAddList) {
                    log.error("————————————————————————————添加操作步骤失败————————————————————————————>");
                } else {
                    log.error("————————————————————————————添加操作步骤成功————————————————————————————>");
                }

                chargeCustomOrderInfoMapper.insertChargeCustomOrderInfo(orderInfo);

                // 业务逻辑结束 回传给小程序端唤起支付
                return wxpay;
            }
            wxpay.setStatus(500);
            wxpay.setMsg("微信统一下单：失败!");
            return wxpay;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信统一下单发生异常————————————————————————————>" + e);
            wxpay.setStatus(500);
            wxpay.setMsg("微信统一下单失败!");
        }
        wxpay.setStatus(500);
        wxpay.setMsg("微信统一下单：失败!");
        return wxpay;
    }

    /**
     * 申请退款
     */
    @Transactional
    public WxPay refund(WxPay wxpay) {
        if (StringUtils.isEmpty(wxpay.getMoney())
                || StringUtils.isEmpty(wxpay.getOutTradeNo())
        ) {
            wxpay.setStatus(500);
            wxpay.setMsg("参数错误,微信申请退款失败!");
            return wxpay;
        }
        try {
            //根据商户订单号查询
            ChargeCustomOrderInfo orderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(wxpay.getOutTradeNo());
            //查询场站信息
            ChargeStation chargeStation = chargeStationMapper.selectChargeStationByChargeStationCode(orderInfo.getChargeStationCode());

            if (orderInfo == null || orderInfo.getOrderInfoStatus() == null) {
                wxpay.setStatus(200);
                wxpay.setMsg("订单号错误,微信申请退款失败!");
                return wxpay;
            }

            if ("4".equals(orderInfo.getOrderInfoStatus()) || "5".equals(orderInfo.getOrderInfoStatus())) {
                wxpay.setStatus(200);
                wxpay.setMsg("微信申请退款已完成，微信申请退款失败!");
                return wxpay;
            }

            OrderRefundInfo order = new OrderRefundInfo();
            order.setAppid(Configure.getAppID());
            order.setMch_id(chargeStation.getMchId());
            order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
            order.setOut_trade_no(wxpay.getOutTradeNo());
            if (StringUtils.isEmpty(orderInfo.getOutRefundNo())) {
                order.setOut_refund_no(RandomStringGenerator.getRandomStringByLength(32));
            } else {
                order.setOut_refund_no(orderInfo.getOutRefundNo());
            }
            order.setNotify_url(Configure.getRefund_notify_url()); //回调地址
            //订单总金额
            order.setTotal_fee(orderInfo.getTotalMoney().multiply(new BigDecimal("100")).intValue());
            //orderInfo.getTotalMoney().multiply(new BigDecimal("100")).intValue()
            //退款金额
            order.setRefund_fee(new BigDecimal(wxpay.getMoney()).multiply(new BigDecimal("100")).intValue());
            //order.setSign_type("MD5");
            //生成签名
            String sign = Signature.getSign(order, chargeStation.getMchKey());
            order.setSign(sign);

            orderInfo.setOutRefundNo(order.getOut_refund_no());
            int i = chargeCustomOrderInfoMapper.updateChargeCustomOrderInfo(orderInfo);
            if (i != 1) {
                wxpay.setStatus(500);
                wxpay.setMsg("微信申请退款失败!");
                return wxpay;
            }

            String result = HttpRequest.doRefund(Configure.getRefund_url(), order, chargeStation.getMchId());
//            System.out.println(result);

            XStream xStream = new XStream();
            xStream.alias("xml", RefundReturnInfo.class);
            xStream.ignoreUnknownElements();
            Class<?>[] classes = new Class[]{RefundReturnInfo.class};
            xStream.allowTypes(classes);
            Object preOrderResult = xStream.fromXML(result);
            ObjectMapper objectMapper = new ObjectMapper();
            RefundReturnInfo returnInfo = objectMapper.convertValue(preOrderResult, RefundReturnInfo.class);

            if ("SUCCESS".equals(returnInfo.getReturn_code())) {
                //逻辑处理
                //修改订单状态为已申请
                orderInfo.setOrderInfoStatus("4");
//                orderInfo.setRefundAmount(new BigDecimal(returnInfo.getRefund_fee()).divide(new BigDecimal("100")));
                orderInfo.setRefundId(returnInfo.getRefund_id());
                i = chargeCustomOrderInfoMapper.updateChargeCustomOrderInfo(orderInfo);
                if (i == 1) {
                    wxpay.setStatus(200);
                    wxpay.setMsg("微信申请退款成功!");
                    return wxpay;
                }
            }

            wxpay.setStatus(500);
            wxpay.setMsg("微信申请退款失败!");
            return wxpay;
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("微信申请退款发生异常————————————————————————————》" + e);
            wxpay.setStatus(500);
            wxpay.setMsg("微信申请退款失败!");
            return wxpay;
        }
    }

    /**
     * 查询退款 退款有一定延时，用零钱支付的退款20分钟内到账，银行卡支付的退款3个工作日后重新查询退款状态。
     */
    @Transactional
    public WxPay refundQuery(WxPay wxpay) {
        //根据商户订单号查询
        ChargeCustomOrderInfo orderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(wxpay.getOutTradeNo());
        //查询场站信息
        ChargeStation chargeStation = chargeStationMapper.selectChargeStationByChargeStationCode(orderInfo.getChargeStationCode());

        if ("5".equals(orderInfo.getOrderInfoStatus())) {
            wxpay.setStatus(200);
            wxpay.setMsg("微信退款已完成，微信查询退款失败!");
            return wxpay;
        }

        try {
            QueryRefundInfo order = new QueryRefundInfo();
            order.setAppid(Configure.getAppID());
            order.setMch_id(chargeStation.getMchId());
            order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
            order.setOut_trade_no(wxpay.getOutTradeNo());
            //order.setSign_type("MD5");
            //生成签名
            String sign = Signature.getSign(order, chargeStation.getMchKey());
            order.setSign(sign);

            String result = HttpRequest.sendPost(Configure.getRefundquery_url(), order);
//            System.out.println(result);

            XStream xStream = new XStream();
            xStream.alias("xml", QueryRefundReturnInfo.class);
            xStream.ignoreUnknownElements();
            Class<?>[] classes = new Class[]{QueryRefundReturnInfo.class};
            xStream.allowTypes(classes);
            Object preOrderResult = xStream.fromXML(result);
            ObjectMapper objectMapper = new ObjectMapper();
            QueryRefundReturnInfo returnInfo = objectMapper.convertValue(preOrderResult, QueryRefundReturnInfo.class);


            if ("SUCCESS".equals(returnInfo.getReturn_code())) {

                if (orderInfo.getRefundAmount().compareTo(new BigDecimal(returnInfo.getRefund_fee()).multiply(new BigDecimal("100"))) == 0) { //退款金额对比
                    //逻辑处理
                    //修改订单状态为已退款
                    orderInfo.setOrderInfoStatus("5");
                    orderInfo.setOrderStatus("2");
                    int i = chargeCustomOrderInfoMapper.updateChargeCustomOrderInfo(orderInfo);
                    if (i != 1) {
                        wxpay.setStatus(500);
                        wxpay.setMsg("修改订单状态失败，微信查询退款失败!");
                        return wxpay;
                    }
                }
                wxpay.setStatus(200);
                wxpay.setMsg("微信查询退款成功!");
                return wxpay;
            }

            wxpay.setStatus(500);
            wxpay.setMsg("请求返回信息错误，查询退款失败!");
            wxpay.setData(null);
            return wxpay;
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("微信订单查询：发生异常==============》" + e);
            wxpay.setStatus(500);
            wxpay.setMsg("查询退款失败!");
            return wxpay;
        }
    }
}
